<script setup lang="ts">
import { io } from 'socket.io-client'
import 'webrtc-adapter'

enum roleType {
	sender = 'sender',
	receiver = 'receiver',
}

enum socketEvent {
	connect = 'connect',
	hello = 'hello',
	toIO = 'toIO',
	toSocket = 'toSocket',
	askSender = 'askSender',
	disconnect = 'disconnect',
}

const stream = ref<MediaStream>()
const roomId = ref('')
const disabledCamera = ref(false)
const disabledScreen = ref(false)
const peer = new RTCPeerConnection()

const socket = io(`https://${location.hostname}:8099`, {
	reconnection: false,
	transports: ['websocket'],
	query: {
		role: roleType.sender,
	},
})

async function sendMedia(stream: MediaStream) {
	stream.getTracks().forEach((track) => {
		peer.addTrack(track, stream)
	})

	const offer = await peer.createOffer()
	await peer.setLocalDescription(offer)

	socket.emit(socketEvent.toIO, {
		type: offer.type,
		sdp: offer.sdp,
		roomId: roomId.value,
	})
}

async function shareCamera() {
	try {
		stream.value = await navigator.mediaDevices.getUserMedia({
			video: true,
		})
	} catch (e) {
		toast.error(e)
		disabledCamera.value = true
	}
}

async function shareScreen() {
	try {
		stream.value = await navigator.mediaDevices.getDisplayMedia()
	} catch (e) {
		toast.error(e)
		disabledScreen.value = true
	}
}

watch(stream, (newValue, oldValue) => sendMedia(newValue as MediaStream))

peer.onicecandidate = (e) => {
	if (e.candidate) {
		socket.emit(socketEvent.toIO, {
			type: 'offer_ice',
			iceCandidate: e.candidate,
			roomId: roomId.value,
		})
	}
}

socket.on(socketEvent.connect, () => {
	toast.success(`我的ID是\n${socket.id}\n已连接${location.hostname}:8099`)
})

socket.on(socketEvent.hello, (data) => {
	roomId.value = data.roomId
	toast.success(`申请到的房间ID是${roomId.value}`)
})

socket.on(socketEvent.toSocket, (data) => {
	const { type, sdp, iceCandidate } = data
	switch (type) {
		case 'answer':
			peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }))
			break

		case 'answer_ice':
			peer.addIceCandidate(iceCandidate)
			break

		default:
			break
	}
})

socket.on(socketEvent.askSender, () => sendMedia(stream.value as MediaStream))

socket.on(socketEvent.disconnect, () => {
	toast.error('失去连接')
})
</script>

<template>
	<el-container class="w-full">
		<el-header
			class="h-20 text-light-200 bg-sky-300 font-size-10 flex h-screen items-center justify-center"
		>
			<span v-show="roomId === ''">还没有房间</span>
			<span v-show="roomId !== ''">我的房间密码{{ roomId }}</span>
		</el-header>
		<el-main class="font-size-20 text-light-200">
			<button
				ref="camera-button"
				type="button"
				class="w-full h-75 mb-5 rounded-3xl bg-orange-300 active:bg-orange-400"
				@click="shareCamera"
				:disabled="disabledCamera"
			>
				共享摄像头
			</button>
			<button
				ref="screen-button"
				type="button"
				class="w-full h-75 mt-5 rounded-3xl bg-red-300 active:bg-red-400"
				@click="shareScreen"
				:disabled="disabledScreen"
			>
				共享桌面
			</button>
		</el-main>
	</el-container>
</template>

<style></style>
